Do more Marylanders donate to in-state or out-of-state candidates?
Which out-of-state candidates received the most donations and the
greatest amount of money in donations? What are the demographics of
people who donate to Maryland races only? To out-of-state races only?
(using voter data OR using census data to see if those donors are
clustered in specific locations, and, if they are, what the makeups of
those locations are) Among top Maryland donors, what professions donate
the most money to senate campaigns? What’s the makeup of donations
received by Hogan and Alsobrooks? What percentage of their overall
donations were large amounts of money (to be defined, but > $1000,
for example) vs small amounts? Which party tends to donate more to
out-of-state races?
We refined our dataset further by deciding to focus on individual
donations made to senate races by donors in Maryland. Using the FEC
website, we downloaded a dataset that met those parameters. We cleaned
the data by removing unnecessary columns and renaming the columns where
needed. We decided to limit our dataset to donations made in 2024 to
ensure that the donations were made after the primary and before the
general election. We hoped this would limit the number of candidates
receiving donations, since most donations will go toward one of two
parties in a certain race.
We also cleaned the data-set, removing numerous columns that were N/A
or that were unnecessary to our project. We also had to rename one
column and then filter to only the report year of 2024 to limit the
donations. To answer our first question and questions, we’ll need to
separate the out-of-state candidates from in-state candidates, but this
should be easy because we’ll just need to filter out the Hogan and
Alsobrooks committees to isolate the out-of-state candidates receiving
donations. To answer our third question, we’ll need to either call in
demographic data from the census or identify specific locations with
clusters of donations, and look up information about those locations
using census.gov. Question #4 asks about the professions of donors. One
obvious challenge here is that professions and titles are often spelled
or worded differently, even if they describe the same job– in this
dataset, there are 2,738 different professions listed. To try to combat
this, we will use open refine to reduce the number of occupations with
slight variations in spelling or wording. We will then limit the data
set to the top 1000 donations to make the analysis more manageable. We
can also make some broad observations about the data even without
cleaning the professions– for example, it’s obvious that the most
donations come from people who say they are “not employed” (45568) or
“retired” (29424). The next highest number of donations is more than
20,000 donations less than the number of donations from retired people.
There are 207 committees that received donations in our dataset.
Originally, we thought that we would use open refine to sort the
committees by candidate name, because we thought that most candidates
would have multiple committees. However, we found that this was actually
pretty uncommon, and we weren’t able to match any names using open
refine, once we uploaded our csv. For question 5, we need to do some
extra research to decide how to define large donations. One idea is to
find the average or median donation, and use that number as the dividing
line between small and large donations. Another idea is to see if
there’s an agreed-upon definition by people who work on campaigns or
political scientists. We have one extra question (#6) that we would like
to answer, but it involves party-level analysis that we can’t do because
we don’t have the political parties of the donors in this data, and we
don’t have anything in this data that indicates the party of each
candidate. To answer this question, we could join this data with data
from Act Blue and Win Red to identify the parties of donors. We can also
probably find a dataset with the committee names and parties for all
senate candidates, and join that dataset with ours.
Turn off scientific notation
<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxub3B0aW9ucyhzY2lwZW49OTk5KVxubGlicmFyeSh0aWR5dmVyc2UpXG5saWJyYXJ5KGx1YnJpZGF0ZSlcblxuXG5gYGAifQ== -->
```r
options(scipen=999)
library(tidyverse)
library(lubridate)
```
<!-- rnb-source-end -->
```r
options(scipen=999)
library(tidyverse)
library(lubridate)
<!-- rnb-source-end -->
<!-- rnb-output-end -->
<!-- rnb-chunk-end -->
<!-- rnb-text-begin -->
<!-- rnb-text-end -->
<!-- rnb-chunk-begin -->
<!-- rnb-output-begin eyJkYXRhIjoiXG48IS0tIHJuYi1zb3VyY2UtYmVnaW4gZXlKa1lYUmhJam9pWUdCZ2NseHVhVzV6ZEdGc2JDNXdZV05yWVdkbGN5Z25kR2xrZVdObGJuTjFjeWNwWEc1Z1lHQWlmUT09IC0tPlxuXG5gYGByXG5pbnN0YWxsLnBhY2thZ2VzKCd0aWR5Y2Vuc3VzJylcbmBgYFxuXG48IS0tIHJuYi1zb3VyY2UtZW5kIC0tPlxuIn0= -->
<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuaW5zdGFsbC5wYWNrYWdlcygndGlkeWNlbnN1cycpXG5gYGAifQ== -->
```r
install.packages('tidycensus')
There is a binary version available but the source version is later:
installing the source package ‘tidycensus’
trying URL 'https://cran.rstudio.com/src/contrib/tidycensus_1.6.7.tar.gz'
Content type 'application/x-gzip' length 2262396 bytes (2.2 MB)
==================================================
downloaded 2.2 MB
* installing *source* package ‘tidycensus’ ...
** package ‘tidycensus’ successfully unpacked and MD5 sums checked
** using staged installation
** R
** data
*** moving datasets to lazyload DB
* removing ‘/Library/Frameworks/R.framework/Versions/4.2/Resources/library/tidycensus’
* restoring previous ‘/Library/Frameworks/R.framework/Versions/4.2/Resources/library/tidycensus’
Warning in install.packages :
installation of package ‘tidycensus’ had non-zero exit status
The downloaded source packages are in
‘/private/var/folders/2l/xcvc2w597t9714c985cwdbr40000gp/T/RtmpfQuLsL/downloaded_packages’
library(tidycensus)
md_senate_contributions <- read_csv("data/md_senate_contributions.csv") |>
print(column_names)
New names:Warning: One or more parsing issues, call `problems()` on your data frame for details, e.g.:
dat <- vroom(...)
problems(dat)Rows: 115275 Columns: 79── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (44): committee_id, committee_name...2, report_type, line_number, transaction_id, entity_type, entity_type_desc, unused_contbr_id, ...
dbl (11): report_year, image_number, file_number, contributor_zip, contribution_receipt_amount, contributor_aggregate_ytd, conduit_comm...
lgl (22): committee_name...9, recipient_committee_org_type, memo_code_full, candidate_id, candidate_name, candidate_first_name, candida...
dttm (2): contribution_receipt_date, load_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#clean data
cleaned_data <- md_senate_contributions |>
select( -unused_contbr_id, -committee_name...9, -recipient_committee_org_type, -contributor_suffix, -contributor_street_2, -contributor_id, -memo_code, -memo_code_full, -candidate_id, -candidate_name, -candidate_first_name, -candidate_last_name, -candidate_middle_name, -candidate_prefix, -candidate_suffix, -candidate_office, -candidate_office_full, -candidate_office_state, -candidate_office_state_full, -candidate_office_district, -conduit_committee_id, -conduit_committee_name, -conduit_committee_street1, -conduit_committee_street2, -conduit_committee_city, -conduit_committee_state, -conduit_committee_zip, -donor_committee_name, -national_committee_nonfederal_account, -election_type_full, -increased_limit, -is_individual) |>
rename(committee_name = `committee_name...2`) |>
filter(report_year == 2024)
colnames(cleaned_data)
[1] "committee_id" "committee_name" "report_year" "report_type"
[5] "image_number" "line_number" "transaction_id" "file_number"
[9] "entity_type" "entity_type_desc" "contributor_prefix" "contributor_name"
[13] "recipient_committee_type" "recipient_committee_designation" "contributor_first_name" "contributor_middle_name"
[17] "contributor_last_name" "contributor_street_1" "contributor_city" "contributor_state"
[21] "contributor_zip" "contributor_employer" "contributor_occupation" "receipt_type"
[25] "receipt_type_desc" "receipt_type_full" "contribution_receipt_date" "contribution_receipt_amount"
[29] "contributor_aggregate_ytd" "election_type" "fec_election_type_desc" "fec_election_year"
[33] "amendment_indicator" "amendment_indicator_desc" "schedule_type_full" "load_date"
[37] "original_sub_id" "back_reference_transaction_id" "back_reference_schedule_name" "filing_form"
[41] "link_id" "memo_text" "two_year_transaction_period" "schedule_type"
[45] "sub_id" "pdf_url" "line_number_label"
most_contributions <- cleaned_data |>
select(committee_name, contribution_receipt_amount) |>
group_by(committee_name) |>
summarize(total_contribution = sum(contribution_receipt_amount, na.rm = TRUE)) |>
arrange(desc(total_contribution))
cleaned_data |>
write_csv("data/cleaned_md_senate_contributions.csv")
data <- read_delim("data/ccl.txt", delim = "|", col_names = FALSE)
Rows: 8568 Columns: 7── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "|"
chr (4): X1, X4, X5, X6
dbl (3): X2, X3, X7
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
cleaned_data_ccl <- data |>
rename(candidate_id = X1,candidate_election_year = X2, fec_election_year = X3, committee_id = X4,committee_type = X5,committee_design = X6, linkage_id = X7)
#inner join the committee id and fec election year
joined_data <- inner_join(cleaned_data, cleaned_data_ccl, by = c("committee_id", "fec_election_year"))
Warning: Detected an unexpected many-to-many relationship between `x` and `y`.
#insert the candidate data
candidate_data <- read_delim("data/candidate_data.txt", delim = "|", col_names = FALSE) |>
select(X1, X2, X3, X5) |>
rename(candidate_id = X1, candidate_name = X2, candidate_party = X5)
Rows: 3824 Columns: 30── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "|"
chr (7): X1, X2, X3, X5, X19, X20, X28
dbl (18): X4, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X26, X27, X29, X30
lgl (5): X21, X22, X23, X24, X25
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
candidate_joined_data <- inner_join(joined_data, candidate_data, by =c("candidate_id"))
#include only these rows
final_data <- candidate_joined_data |>
select(committee_id, committee_name, report_year, entity_type_desc,contributor_prefix, contributor_name, contributor_first_name, contributor_last_name, contributor_middle_name, contributor_street_1,contributor_city, contributor_state, contributor_zip,contributor_employer, contributor_occupation, contribution_receipt_date, contribution_receipt_amount, contributor_aggregate_ytd,memo_text,pdf_url, candidate_id, candidate_election_year)
Q1: Do more Marylanders donate to in-state or out-of-state
candidates?
final_data_states <- final_data |>
mutate(state = substr(candidate_id, 3, 4))
state_contributions <- final_data_states |>
group_by(state) |>
summarise(
contribution_count = n(),
total_contribution = sum(contribution_receipt_amount, na.rm = TRUE)
)
maryland_contrib <- state_contributions |>
filter(state == "MD") |>
summarise(total_maryland_contrib = sum(total_contribution, na.rm = TRUE))
other_states_contrib <- state_contributions |>
filter(state != "MD") |>
summarise(total_other_states_contrib = sum(total_contribution, na.rm = TRUE))
comparison <- data.frame(
state = c("Maryland", "Other States"),
total_contribution = c(maryland_contrib$total_maryland_contrib, other_states_contrib$total_other_states_contrib)
)
A: Montana was surprisingly the state with the most contributions —
edging Maryland with 202 more contributions Maryland. Maryland received
the highest total sum however, with $5,516,562.24. That was
$4,074,226.07 more than the next highest state, which was Montana. The
other states combined recieved $7,358,970, a little less than two
million more than just the state of Maryland.
Q2: Which out-of-state candidates received the most donations and the
greatest amount of money in donations?
final_data_no_md <- final_data_states |>
filter(state != "MD")
contributions_summary <- final_data_no_md |>
group_by(committee_name) |>
summarise(
num_contributions = n(),
total_contribution_sum = sum(contribution_receipt_amount, na.rm = TRUE)
) |>
arrange(committee_name)
A2: Jon Tester, Sherrod Brown and Ruben Gallego were the top three in
that order for both contributions recieved and the sum of contributions.
The similarity between the three of them is that they were all Democrats
running in tightly contested races. Brown was the only to lose his race.
Jon Tester also clearly recieved more than the other two — which
explains why Montana received so many more out-of-state contributions
than other states. Montanans for Tester received 3,679 more
contributions and $238,017.96 more in total contributions compared to
Friends of Sherrod Brown.
Q3: What are the demographics of people who donate to Maryland races
only? To out-of-state races only?
Step 1: find people who donate to ONLY Maryland races.
maryland_only_donors <- final_data_states|>
group_by(contributor_name) |>
summarize(only_md = all(state == "MD")) |>
filter(only_md) |>
select(contributor_name)
full_maryland_only_donors <- final_data_states |>
filter(contributor_name %in% maryland_only_donors$contributor_name)
zips_full_maryland_only_donors <- full_maryland_only_donors |>
group_by(contributor_name, contributor_zip) |>
summarize(
num_donations = n(),
total_donated = sum(contribution_receipt_amount)
)|>
arrange(desc(num_donations))
`summarise()` has grouped output by 'contributor_name'. You can override using the `.groups` argument.
md_zip_summary <- zips_full_maryland_only_donors |>
group_by(contributor_zip) |>
summarize(
num_donations = n(),
total_donated = sum(total_donated)
) |>
arrange(desc(num_donations))
all_zcta <- get_acs(
geography = "zcta",
variables = c(
"B01003_001",
"B01002_001", #= "median_age",
"B19013_001", # = "median_income",
"B02001_002", # = "white_alone",
"B02001_003", # = "black_alone",
"B02001_004", # = "native_american",
"B02001_005", #= "asian_alone",
"B02001_006", # = "hawaiian_pacific",
"B02001_007", # = "other_race",
"B02001_008", # = "two_or_more_races"
"B03002_012E"),
year = 2022,
survey = "acs5",
output = "wide"
)
Getting data from the 2018-2022 5-year ACS
all_zcta <- all_zcta %>%
rename(
total_population = B01003_001E,
median_age = B01002_001E,
median_income = B19013_001E,
white_alone = B02001_002E,
black_alone = B02001_003E,
native_american = B02001_004E,
asian_alone = B02001_005E,
hawaiian_pacific = B02001_006E,
other_race = B02001_007E,
two_or_more_races = B02001_008E,
hispanic_or_latino = B03002_012E
)
zips_full_maryland_only_donors <- zips_full_maryland_only_donors |>
mutate(
contributor_zip = substr(contributor_zip, 1, 5),
contributor_zip = sprintf("%05s", contributor_zip)
)
zips_full_maryland_only_donors <- zips_full_maryland_only_donors |>
mutate(contributor_zip = as.character(contributor_zip))
merged_data_md <- zips_full_maryland_only_donors %>%
left_join(all_zcta, by = c("contributor_zip" = "GEOID"))
summarized_md_donor_demos_by_zip <- merged_data_md %>%
group_by(contributor_zip) |>
summarize(
total_population = first(total_population),
median_age = first(median_age),
median_income = first(median_income),
white_alone = first(white_alone),
black_alone = first(black_alone),
native_american = first(native_american),
asian_alone = first(asian_alone),
hawaiian_pacific = first(hawaiian_pacific),
other_race = first(other_race),
hispanic_or_latino = first(hispanic_or_latino),
two_or_more_races = first(two_or_more_races),
num_donations = n(),
total_amt_donated = sum(total_donated, na.rm = TRUE)
) |>
arrange(desc(num_donations)) |>
mutate(
white_alone_per_capita = white_alone / total_population,
black_alone_per_capita = black_alone / total_population,
native_american_per_capita = native_american / total_population,
asian_alone_per_capita = asian_alone / total_population,
hawaiian_pacific_per_capita = hawaiian_pacific / total_population,
other_race_per_capita = other_race / total_population,
hispanic_or_latino_per_capita = hispanic_or_latino / total_population,
two_or_more_races_per_capita = two_or_more_races / total_population,
median_income_per_capita = median_income / total_population
) |>
mutate(
white_alone_percent = white_alone_per_capita * 100,
black_alone_percent = black_alone_per_capita * 100,
native_american_percent = native_american_per_capita * 100,
asian_alone_percent = asian_alone_per_capita * 100,
hawaiian_pacific_percent = hawaiian_pacific_per_capita * 100,
other_race_percent = other_race_per_capita * 100,
hispanic_or_latino_percent = hispanic_or_latino_per_capita *100,
two_or_more_races_percent = two_or_more_races_per_capita * 100,
median_income_per_capita = median_income_per_capita * 100
) |>
mutate(
amt_donated_per_resident = total_amt_donated / total_population
) |>
select(where(~ !all(is.na(.))))
cleaner_md_donor_demos <- summarized_md_donor_demos_by_zip |>
select(-matches("_per_capita"), -"native_american", -"hawaiian_pacific", -"other_race", -"two_or_more_races", -"white_alone", -"black_alone", -"asian_alone")
#repeat for out of state donors
out_of_state_donors <- final_data_states |>
filter(state != "MD")
xmaryland_donors <- final_data_states |>
filter(state == "MD")
out_of_state_only_donors <- out_of_state_donors |>
filter(!contributor_name %in% xmaryland_donors$contributor_name) |>
group_by(contributor_name, contributor_zip) |>
summarize(
num_donations = n(),
total_donated = sum(contribution_receipt_amount)
) |>
arrange(desc(num_donations))
`summarise()` has grouped output by 'contributor_name'. You can override using the `.groups` argument.
out_of_state_only_donors <- out_of_state_only_donors |>
mutate(
contributor_zip = substr(contributor_zip, 1, 5),
contributor_zip = sprintf("%05s", contributor_zip)
)
merged_data_oos <- out_of_state_only_donors|>
left_join(all_zcta, by = c("contributor_zip" = "GEOID"))
cleaner_oos_donor_demos <- merged_data_oos |>
group_by(contributor_zip) |>
summarize(
total_population = first(total_population),
median_age = first(median_age),
median_income = first(median_income),
white_alone = first(white_alone),
black_alone = first(black_alone),
native_american = first(native_american),
asian_alone = first(asian_alone),
hawaiian_pacific = first(hawaiian_pacific),
other_race = first(other_race),
hispanic_or_latino = first(hispanic_or_latino),
two_or_more_races = first(two_or_more_races),
num_donations = n(),
total_amt_donated = sum(total_donated, na.rm = TRUE)
) |>
arrange(desc(num_donations)) |>
mutate(
white_alone_per_capita = white_alone / total_population,
black_alone_per_capita = black_alone / total_population,
native_american_per_capita = native_american / total_population,
asian_alone_per_capita = asian_alone / total_population,
hawaiian_pacific_per_capita = hawaiian_pacific / total_population,
other_race_per_capita = other_race / total_population,
hispanic_or_latino_per_capita = hispanic_or_latino / total_population,
two_or_more_races_per_capita = two_or_more_races / total_population,
median_income_per_capita = median_income / total_population
) |>
mutate(
white_alone_percent = white_alone_per_capita * 100,
black_alone_percent = black_alone_per_capita * 100,
native_american_percent = native_american_per_capita * 100,
asian_alone_percent = asian_alone_per_capita * 100,
hawaiian_pacific_percent = hawaiian_pacific_per_capita * 100,
other_race_percent = other_race_per_capita * 100,
hispanic_or_latino_percent = hispanic_or_latino_per_capita *100,
two_or_more_races_percent = two_or_more_races_per_capita * 100,
median_income_per_capita = median_income_per_capita * 100
)
cleaner_oos_donor_demos <- cleaner_oos_donor_demos |> select(-matches("_per_capita"), -"native_american", -"hawaiian_pacific", -"other_race", -"two_or_more_races", -"white_alone", -"black_alone", -"asian_alone") |>
mutate(
amt_donated_per_resident = total_amt_donated / total_population
) |>
select(where(~ !all(is.na(.))))
head(merged_data_oos)
cleaner_oos_donor_demos |>
mutate(
contributor_zip = as.character(contributor_zip), # Ensure ZIP codes are strings
contributor_zip = str_pad(contributor_zip, width = 5, # Pad with leading zeros to ensure 5 digits
side = "left", pad = "0"),
contributor_zip = ifelse(str_detect(contributor_zip, "^\\d{5}$"), # Keep only valid 5-digit ZIP codes
contributor_zip, NA))
cleaner_oos_donor_demos |> arrange(desc(amt_donated_per_resident)) |> write_csv("cleaner_oos_donor_demos.csv")
cleaner_md_donor_demos |>
mutate(
contributor_zip = as.character(contributor_zip), # Ensure ZIP codes are strings
contributor_zip = str_pad(contributor_zip, width = 5, # Pad with leading zeros to ensure 5 digits
side = "left", pad = "0"),
contributor_zip = ifelse(str_detect(contributor_zip, "^\\d{5}$"), # Keep only valid 5-digit ZIP codes
contributor_zip, NA)) |>
arrange(desc(amt_donated_per_resident)) |> write_csv("cleaner_md_donor_demos.csv")
cleaner_oos_donor_demos |>
write_csv(“cleaner_oos_donor_demos.csv”)
It looks like in this data, the top contributing zip codes are the
same for out-of-state and in-state donations. The top out-of-state
donors donated much more than the in-state donors, and there were more
of them in the top zip codes. A top in-state donor zip code is Anapolis,
and doesn’t appear in the top ten zip codes for out-of-state.
As we keep going to answer this question, we should calculate the
amount donated per person. We should consider presenting this data with
two maps side-by-side.
Question 4: Among top Maryland donors, what professions donate the
most money to senate campaigns?
individual_donors <- final_data_states|>
group_by(contributor_name, contributor_zip, contributor_occupation, contributor_employer) |>
summarize(
num_donations = n(),
total_donated = sum(contribution_receipt_amount)
) |>
arrange(desc(num_donations))
jobs_to_clean <- individual_donors |>
group_by(contributor_occupation) |>
summarize(
number_jobs = n(),
num_donations = n(),
total_donations = sum(total_donated)
) |> arrange(desc(number_jobs)) |>
write_csv("jobs_to_clean.csv")
boss_to_clean <- individual_donors |>
group_by(contributor_employer) |>
summarize(
number_jobs = n(),
num_donations = n(),
total_donations = sum(total_donated)
) |> arrange(desc(number_jobs)) |>
write_csv("boss_to_clean.csv")
clean_employer <- read_csv("cleaned_boss.csv")
clean_occupation <- read_csv("clean_jobs.csv")
clean_occupation |>
group_by(cleaned_jjobs) |>
summarize(
number_jobs = n(),
num_donations = n(),
total_donated = sum(total_donations)) |>
arrange(desc(number_jobs))
clean_occupation |>
group_by(cleaned_jjobs) |>
summarize(
number_jobs = n(),
num_donations = n(),
total_donated = sum(total_donations)) |>
arrange(desc(total_donated))
clean_employer |>
group_by(cleaned_boss) |>
summarize(
number_jobs = n(),
num_donations = n(),
total_donated = sum(total_donations)
) |>
arrange(desc(number_jobs))
To answer this question, I put a csv of occupations into OpenRefine.
We originally planned to limit the data set, but I found that there were
only 1,963 job titles in the data set, which seemed like a reasonable
number to refine down into a smaller list of jobs.
To do this, I grouped certain jobs into categories like “director”
and “executive” – so job titles like “sales director” went into the
“director” category.
I think the OpenRefine method may be flawed/not tell us very much
because I was only able to get the list down to 1,464 jobs after about 1
hour of refining. I also worry that the categorizing method I used
obsures information that might be important – Director of Sales is
different from Director of Education, for example, and these jobs were
grouped into the same position. And there are such variations in job
title that I was not able to categorize all job titles well.
What we can tell from this data is that the most frequently-held jobs
among Maryland donors are leadership/management positions, so likely
well-paid. The most money was donated by people who are not employed or
retired.
We should consider repeating this question with information about
employers. I’ve started to do this in OpenRefine, but this will take
longer, because there are more than 7,000 different employers. However,
many of these seem to be able to be reconciled in OpenRefine. And I’m
interested to see how many donations/how much money was donated by
people who work for top employers in Maryland, like Johns Hopkins.
#Question 5: What’s the makeup of donations received by Hogan and
Alsobrooks? What percentage of their overall donations were large
amounts of money (to be defined, but > $1000, for example) vs small
amounts?
hogan_filtered_data <- final_data |>
filter(committee_name %in% c("HOGAN FOR MARYLAND INC."))
large_donation_threshold <- 1000
hogan_filtered_data |> mutate( donation_category = ifelse(contribution_receipt_amount > large_donation_threshold, "Large", "Small") )
hogan_category_totals <- hogan_filtered_data |>
mutate(donation_category = ifelse(contribution_receipt_amount > large_donation_threshold, "Large", "Small")) |>
group_by(donation_category) |>
summarise(total_amount = sum(contribution_receipt_amount, na.rm = TRUE), .groups = "drop")
hogan_category_totals %>% mutate( percentage = total_amount / sum(total_amount) * 100 )
hogan_category_totals
alsobrooks_filtered_data <- final_data |>
filter(committee_name %in% c("ALSOBROOKS FOR SENATE"))
large_donation_threshold <- 1000
alsobrooks_category_totals <- alsobrooks_filtered_data |>
mutate(donation_category = ifelse(contribution_receipt_amount > large_donation_threshold, "Large", "Small")) |>
group_by(donation_category) |>
summarise(total_amount = sum(contribution_receipt_amount, na.rm = TRUE), .groups = "drop")
alsobrooks_category_totals %>% mutate( percentage = total_amount / sum(total_amount) * 100 )
alsobrooks_category_totals
A5: Here we see that Hogan receives signficantly more money in
general in comparison to Alsobrooks. Additionally, Hogan receives many
more large donations (in excess of millions) in comparison to
Alsobrooks. Whereas, the small donations are around 600,000 more. This
shows that eithe Hogan has a larger “fan base” of people who donate to
him or perhaps his electorate is just wealthier. Additionally,it would
be interesting to note whether Hogan has a higher amount of donations
because he was known before.
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKUiBOb3RlYm9vawpRdWVzdGlvbnMsIHJlZmluZWQ6CgpEbyBtb3JlIE1hcnlsYW5kZXJzIGRvbmF0ZSB0byBpbi1zdGF0ZSBvciBvdXQtb2Ytc3RhdGUgY2FuZGlkYXRlcz8gV2hpY2ggb3V0LW9mLXN0YXRlIGNhbmRpZGF0ZXMgcmVjZWl2ZWQgdGhlIG1vc3QgZG9uYXRpb25zIGFuZCB0aGUgZ3JlYXRlc3QgYW1vdW50IG9mIG1vbmV5IGluIGRvbmF0aW9ucz8gV2hhdCBhcmUgdGhlIGRlbW9ncmFwaGljcyBvZiBwZW9wbGUgd2hvIGRvbmF0ZSB0byBNYXJ5bGFuZCByYWNlcyBvbmx5PyBUbyBvdXQtb2Ytc3RhdGUgcmFjZXMgb25seT8gKHVzaW5nIHZvdGVyIGRhdGEgT1IgdXNpbmcgY2Vuc3VzIGRhdGEgdG8gc2VlIGlmIHRob3NlIGRvbm9ycyBhcmUgY2x1c3RlcmVkIGluIHNwZWNpZmljIGxvY2F0aW9ucywgYW5kLCBpZiB0aGV5IGFyZSwgd2hhdCB0aGUgbWFrZXVwcyBvZiB0aG9zZSBsb2NhdGlvbnMgYXJlKSBBbW9uZyB0b3AgTWFyeWxhbmQgZG9ub3JzLCB3aGF0IHByb2Zlc3Npb25zIGRvbmF0ZSB0aGUgbW9zdCBtb25leSB0byBzZW5hdGUgY2FtcGFpZ25zPyBXaGF04oCZcyB0aGUgbWFrZXVwIG9mIGRvbmF0aW9ucyByZWNlaXZlZCBieSBIb2dhbiBhbmQgQWxzb2Jyb29rcz8gV2hhdCBwZXJjZW50YWdlIG9mIHRoZWlyIG92ZXJhbGwgZG9uYXRpb25zIHdlcmUgbGFyZ2UgYW1vdW50cyBvZiBtb25leSAodG8gYmUgZGVmaW5lZCwgYnV0ID4gJDEwMDAsIGZvciBleGFtcGxlKSB2cyBzbWFsbCBhbW91bnRzPyBXaGljaCBwYXJ0eSB0ZW5kcyB0byBkb25hdGUgbW9yZSB0byBvdXQtb2Ytc3RhdGUgcmFjZXM/CgpXZSByZWZpbmVkIG91ciBkYXRhc2V0IGZ1cnRoZXIgYnkgZGVjaWRpbmcgdG8gZm9jdXMgb24gaW5kaXZpZHVhbCBkb25hdGlvbnMgbWFkZSB0byBzZW5hdGUgcmFjZXMgYnkgZG9ub3JzIGluIE1hcnlsYW5kLiBVc2luZyB0aGUgRkVDIHdlYnNpdGUsIHdlIGRvd25sb2FkZWQgYSBkYXRhc2V0IHRoYXQgbWV0IHRob3NlIHBhcmFtZXRlcnMuIFdlIGNsZWFuZWQgdGhlIGRhdGEgYnkgcmVtb3ZpbmcgdW5uZWNlc3NhcnkgY29sdW1ucyBhbmQgcmVuYW1pbmcgdGhlIGNvbHVtbnMgd2hlcmUgbmVlZGVkLiBXZSBkZWNpZGVkIHRvIGxpbWl0IG91ciBkYXRhc2V0IHRvIGRvbmF0aW9ucyBtYWRlIGluIDIwMjQgdG8gZW5zdXJlIHRoYXQgdGhlIGRvbmF0aW9ucyB3ZXJlIG1hZGUgYWZ0ZXIgdGhlIHByaW1hcnkgYW5kIGJlZm9yZSB0aGUgZ2VuZXJhbCBlbGVjdGlvbi4gV2UgaG9wZWQgdGhpcyB3b3VsZCBsaW1pdCB0aGUgbnVtYmVyIG9mIGNhbmRpZGF0ZXMgcmVjZWl2aW5nIGRvbmF0aW9ucywgc2luY2UgbW9zdCBkb25hdGlvbnMgd2lsbCBnbyB0b3dhcmQgb25lIG9mIHR3byBwYXJ0aWVzIGluIGEgY2VydGFpbiByYWNlLgoKV2UgYWxzbyBjbGVhbmVkIHRoZSBkYXRhLXNldCwgcmVtb3ZpbmcgbnVtZXJvdXMgY29sdW1ucyB0aGF0IHdlcmUgTi9BIG9yIHRoYXQgd2VyZSB1bm5lY2Vzc2FyeSB0byBvdXIgcHJvamVjdC4gV2UgYWxzbyBoYWQgdG8gcmVuYW1lIG9uZSBjb2x1bW4gYW5kIHRoZW4gZmlsdGVyIHRvIG9ubHkgdGhlIHJlcG9ydCB5ZWFyIG9mIDIwMjQgdG8gbGltaXQgdGhlIGRvbmF0aW9ucy4gVG8gYW5zd2VyIG91ciBmaXJzdCBxdWVzdGlvbiBhbmQgcXVlc3Rpb25zLCB3ZeKAmWxsIG5lZWQgdG8gc2VwYXJhdGUgdGhlIG91dC1vZi1zdGF0ZSBjYW5kaWRhdGVzIGZyb20gaW4tc3RhdGUgY2FuZGlkYXRlcywgYnV0IHRoaXMgc2hvdWxkIGJlIGVhc3kgYmVjYXVzZSB3ZeKAmWxsIGp1c3QgbmVlZCB0byBmaWx0ZXIgb3V0IHRoZSBIb2dhbiBhbmQgQWxzb2Jyb29rcyBjb21taXR0ZWVzIHRvIGlzb2xhdGUgdGhlIG91dC1vZi1zdGF0ZSBjYW5kaWRhdGVzIHJlY2VpdmluZyBkb25hdGlvbnMuIFRvIGFuc3dlciBvdXIgdGhpcmQgcXVlc3Rpb24sIHdl4oCZbGwgbmVlZCB0byBlaXRoZXIgY2FsbCBpbiBkZW1vZ3JhcGhpYyBkYXRhIGZyb20gdGhlIGNlbnN1cyBvciBpZGVudGlmeSBzcGVjaWZpYyBsb2NhdGlvbnMgd2l0aCBjbHVzdGVycyBvZiBkb25hdGlvbnMsIGFuZCBsb29rIHVwIGluZm9ybWF0aW9uIGFib3V0IHRob3NlIGxvY2F0aW9ucyB1c2luZyBjZW5zdXMuZ292LiBRdWVzdGlvbiAjNCBhc2tzIGFib3V0IHRoZSBwcm9mZXNzaW9ucyBvZiBkb25vcnMuIE9uZSBvYnZpb3VzIGNoYWxsZW5nZSBoZXJlIGlzIHRoYXQgcHJvZmVzc2lvbnMgYW5kIHRpdGxlcyBhcmUgb2Z0ZW4gc3BlbGxlZCBvciB3b3JkZWQgZGlmZmVyZW50bHksIGV2ZW4gaWYgdGhleSBkZXNjcmliZSB0aGUgc2FtZSBqb2LigJMgaW4gdGhpcyBkYXRhc2V0LCB0aGVyZSBhcmUgMiw3MzggZGlmZmVyZW50IHByb2Zlc3Npb25zIGxpc3RlZC4gVG8gdHJ5IHRvIGNvbWJhdCB0aGlzLCB3ZSB3aWxsIHVzZSBvcGVuIHJlZmluZSB0byByZWR1Y2UgdGhlIG51bWJlciBvZiBvY2N1cGF0aW9ucyB3aXRoIHNsaWdodCB2YXJpYXRpb25zIGluIHNwZWxsaW5nIG9yIHdvcmRpbmcuIFdlIHdpbGwgdGhlbiBsaW1pdCB0aGUgZGF0YSBzZXQgdG8gdGhlIHRvcCAxMDAwIGRvbmF0aW9ucyB0byBtYWtlIHRoZSBhbmFseXNpcyBtb3JlIG1hbmFnZWFibGUuIFdlIGNhbiBhbHNvIG1ha2Ugc29tZSBicm9hZCBvYnNlcnZhdGlvbnMgYWJvdXQgdGhlIGRhdGEgZXZlbiB3aXRob3V0IGNsZWFuaW5nIHRoZSBwcm9mZXNzaW9uc+KAkyBmb3IgZXhhbXBsZSwgaXTigJlzIG9idmlvdXMgdGhhdCB0aGUgbW9zdCBkb25hdGlvbnMgY29tZSBmcm9tIHBlb3BsZSB3aG8gc2F5IHRoZXkgYXJlIOKAnG5vdCBlbXBsb3llZOKAnSAoNDU1NjgpIG9yIOKAnHJldGlyZWTigJ0gKDI5NDI0KS4gVGhlIG5leHQgaGlnaGVzdCBudW1iZXIgb2YgZG9uYXRpb25zIGlzIG1vcmUgdGhhbiAyMCwwMDAgZG9uYXRpb25zIGxlc3MgdGhhbiB0aGUgbnVtYmVyIG9mIGRvbmF0aW9ucyBmcm9tIHJldGlyZWQgcGVvcGxlLiBUaGVyZSBhcmUgMjA3IGNvbW1pdHRlZXMgdGhhdCByZWNlaXZlZCBkb25hdGlvbnMgaW4gb3VyIGRhdGFzZXQuIE9yaWdpbmFsbHksIHdlIHRob3VnaHQgdGhhdCB3ZSB3b3VsZCB1c2Ugb3BlbiByZWZpbmUgdG8gc29ydCB0aGUgY29tbWl0dGVlcyBieSBjYW5kaWRhdGUgbmFtZSwgYmVjYXVzZSB3ZSB0aG91Z2h0IHRoYXQgbW9zdCBjYW5kaWRhdGVzIHdvdWxkIGhhdmUgbXVsdGlwbGUgY29tbWl0dGVlcy4gSG93ZXZlciwgd2UgZm91bmQgdGhhdCB0aGlzIHdhcyBhY3R1YWxseSBwcmV0dHkgdW5jb21tb24sIGFuZCB3ZSB3ZXJlbuKAmXQgYWJsZSB0byBtYXRjaCBhbnkgbmFtZXMgdXNpbmcgb3BlbiByZWZpbmUsIG9uY2Ugd2UgdXBsb2FkZWQgb3VyIGNzdi4gRm9yIHF1ZXN0aW9uIDUsIHdlIG5lZWQgdG8gZG8gc29tZSBleHRyYSByZXNlYXJjaCB0byBkZWNpZGUgaG93IHRvIGRlZmluZSBsYXJnZSBkb25hdGlvbnMuIE9uZSBpZGVhIGlzIHRvIGZpbmQgdGhlIGF2ZXJhZ2Ugb3IgbWVkaWFuIGRvbmF0aW9uLCBhbmQgdXNlIHRoYXQgbnVtYmVyIGFzIHRoZSBkaXZpZGluZyBsaW5lIGJldHdlZW4gc21hbGwgYW5kIGxhcmdlIGRvbmF0aW9ucy4gQW5vdGhlciBpZGVhIGlzIHRvIHNlZSBpZiB0aGVyZeKAmXMgYW4gYWdyZWVkLXVwb24gZGVmaW5pdGlvbiBieSBwZW9wbGUgd2hvIHdvcmsgb24gY2FtcGFpZ25zIG9yIHBvbGl0aWNhbCBzY2llbnRpc3RzLiBXZSBoYXZlIG9uZSBleHRyYSBxdWVzdGlvbiAoIzYpIHRoYXQgd2Ugd291bGQgbGlrZSB0byBhbnN3ZXIsIGJ1dCBpdCBpbnZvbHZlcyBwYXJ0eS1sZXZlbCBhbmFseXNpcyB0aGF0IHdlIGNhbuKAmXQgZG8gYmVjYXVzZSB3ZSBkb27igJl0IGhhdmUgdGhlIHBvbGl0aWNhbCBwYXJ0aWVzIG9mIHRoZSBkb25vcnMgaW4gdGhpcyBkYXRhLCBhbmQgd2UgZG9u4oCZdCBoYXZlIGFueXRoaW5nIGluIHRoaXMgZGF0YSB0aGF0IGluZGljYXRlcyB0aGUgcGFydHkgb2YgZWFjaCBjYW5kaWRhdGUuIFRvIGFuc3dlciB0aGlzIHF1ZXN0aW9uLCB3ZSBjb3VsZCBqb2luIHRoaXMgZGF0YSB3aXRoIGRhdGEgZnJvbSBBY3QgQmx1ZSBhbmQgV2luIFJlZCB0byBpZGVudGlmeSB0aGUgcGFydGllcyBvZiBkb25vcnMuIFdlIGNhbiBhbHNvIHByb2JhYmx5IGZpbmQgYSBkYXRhc2V0IHdpdGggdGhlIGNvbW1pdHRlZSBuYW1lcyBhbmQgcGFydGllcyBmb3IgYWxsIHNlbmF0ZSBjYW5kaWRhdGVzLCBhbmQgam9pbiB0aGF0IGRhdGFzZXQgd2l0aCBvdXJzLgoKIyBUdXJuIG9mZiBzY2llbnRpZmljIG5vdGF0aW9uCgpgYGB7cn0Kb3B0aW9ucyhzY2lwZW49OTk5KQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCgoKYGBgCgpgYGB7cn0KaW5zdGFsbC5wYWNrYWdlcygndGlkeWNlbnN1cycpCmBgYAoKYGBge3J9CmxpYnJhcnkodGlkeWNlbnN1cykKYGBgCgoKCmBgYHtyfQptZF9zZW5hdGVfY29udHJpYnV0aW9ucyA8LSByZWFkX2NzdigiZGF0YS9tZF9zZW5hdGVfY29udHJpYnV0aW9ucy5jc3YiKSB8PgoKCnByaW50KGNvbHVtbl9uYW1lcykKYGBgCgojY2xlYW4gZGF0YQpgYGB7cn0KY2xlYW5lZF9kYXRhIDwtIG1kX3NlbmF0ZV9jb250cmlidXRpb25zIHw+CgpzZWxlY3QoIC11bnVzZWRfY29udGJyX2lkLCAtY29tbWl0dGVlX25hbWUuLi45LCAtcmVjaXBpZW50X2NvbW1pdHRlZV9vcmdfdHlwZSwgLWNvbnRyaWJ1dG9yX3N1ZmZpeCwgLWNvbnRyaWJ1dG9yX3N0cmVldF8yLCAtY29udHJpYnV0b3JfaWQsIC1tZW1vX2NvZGUsIC1tZW1vX2NvZGVfZnVsbCwgLWNhbmRpZGF0ZV9pZCwgLWNhbmRpZGF0ZV9uYW1lLCAtY2FuZGlkYXRlX2ZpcnN0X25hbWUsIC1jYW5kaWRhdGVfbGFzdF9uYW1lLCAtY2FuZGlkYXRlX21pZGRsZV9uYW1lLCAtY2FuZGlkYXRlX3ByZWZpeCwgLWNhbmRpZGF0ZV9zdWZmaXgsIC1jYW5kaWRhdGVfb2ZmaWNlLCAtY2FuZGlkYXRlX29mZmljZV9mdWxsLCAtY2FuZGlkYXRlX29mZmljZV9zdGF0ZSwgLWNhbmRpZGF0ZV9vZmZpY2Vfc3RhdGVfZnVsbCwgLWNhbmRpZGF0ZV9vZmZpY2VfZGlzdHJpY3QsIC1jb25kdWl0X2NvbW1pdHRlZV9pZCwgLWNvbmR1aXRfY29tbWl0dGVlX25hbWUsIC1jb25kdWl0X2NvbW1pdHRlZV9zdHJlZXQxLCAtY29uZHVpdF9jb21taXR0ZWVfc3RyZWV0MiwgLWNvbmR1aXRfY29tbWl0dGVlX2NpdHksIC1jb25kdWl0X2NvbW1pdHRlZV9zdGF0ZSwgLWNvbmR1aXRfY29tbWl0dGVlX3ppcCwgLWRvbm9yX2NvbW1pdHRlZV9uYW1lLCAtbmF0aW9uYWxfY29tbWl0dGVlX25vbmZlZGVyYWxfYWNjb3VudCwgLWVsZWN0aW9uX3R5cGVfZnVsbCwgLWluY3JlYXNlZF9saW1pdCwgLWlzX2luZGl2aWR1YWwpIHw+CgpyZW5hbWUoY29tbWl0dGVlX25hbWUgPSBgY29tbWl0dGVlX25hbWUuLi4yYCkgfD4KCmZpbHRlcihyZXBvcnRfeWVhciA9PSAyMDI0KQoKCmNvbG5hbWVzKGNsZWFuZWRfZGF0YSkKYGBgCgpgYGB7cn0KbW9zdF9jb250cmlidXRpb25zIDwtIGNsZWFuZWRfZGF0YSB8PgpzZWxlY3QoY29tbWl0dGVlX25hbWUsIGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCkgfD4KZ3JvdXBfYnkoY29tbWl0dGVlX25hbWUpIHw+CnN1bW1hcml6ZSh0b3RhbF9jb250cmlidXRpb24gPSBzdW0oY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50LCBuYS5ybSA9IFRSVUUpKSB8PgphcnJhbmdlKGRlc2ModG90YWxfY29udHJpYnV0aW9uKSkgCmNsZWFuZWRfZGF0YSB8PgogIAp3cml0ZV9jc3YoImRhdGEvY2xlYW5lZF9tZF9zZW5hdGVfY29udHJpYnV0aW9ucy5jc3YiKQpkYXRhIDwtIHJlYWRfZGVsaW0oImRhdGEvY2NsLnR4dCIsIGRlbGltID0gInwiLCBjb2xfbmFtZXMgPSBGQUxTRSkKCmNsZWFuZWRfZGF0YV9jY2wgPC0gZGF0YSB8PgpyZW5hbWUoY2FuZGlkYXRlX2lkID0gWDEsY2FuZGlkYXRlX2VsZWN0aW9uX3llYXIgPSBYMiwgZmVjX2VsZWN0aW9uX3llYXIgPSBYMywgY29tbWl0dGVlX2lkID0gWDQsY29tbWl0dGVlX3R5cGUgPSBYNSxjb21taXR0ZWVfZGVzaWduID0gWDYsIGxpbmthZ2VfaWQgPSBYNykKYGBgCgojaW5uZXIgam9pbiB0aGUgY29tbWl0dGVlIGlkIGFuZCBmZWMgZWxlY3Rpb24geWVhciAKCmBgYHtyfQpqb2luZWRfZGF0YSA8LSBpbm5lcl9qb2luKGNsZWFuZWRfZGF0YSwgY2xlYW5lZF9kYXRhX2NjbCwgYnkgPSBjKCJjb21taXR0ZWVfaWQiLCAiZmVjX2VsZWN0aW9uX3llYXIiKSkKYGBgCgojaW5zZXJ0IHRoZSBjYW5kaWRhdGUgZGF0YQpgYGB7cn0KY2FuZGlkYXRlX2RhdGEgPC0gcmVhZF9kZWxpbSgiZGF0YS9jYW5kaWRhdGVfZGF0YS50eHQiLCBkZWxpbSA9ICJ8IiwgY29sX25hbWVzID0gRkFMU0UpIHw+CiAgc2VsZWN0KFgxLCBYMiwgWDMsIFg1KSB8PiAKIHJlbmFtZShjYW5kaWRhdGVfaWQgPSBYMSwgY2FuZGlkYXRlX25hbWUgPSBYMiwgY2FuZGlkYXRlX3BhcnR5ID0gWDUpCgpjYW5kaWRhdGVfam9pbmVkX2RhdGEgPC0gaW5uZXJfam9pbihqb2luZWRfZGF0YSwgY2FuZGlkYXRlX2RhdGEsIGJ5ID1jKCJjYW5kaWRhdGVfaWQiKSkKYGBgCgoKI2luY2x1ZGUgb25seSB0aGVzZSByb3dzIAoKYGBge3J9CgpmaW5hbF9kYXRhIDwtIGNhbmRpZGF0ZV9qb2luZWRfZGF0YSB8PgpzZWxlY3QoY29tbWl0dGVlX2lkLCBjb21taXR0ZWVfbmFtZSwgcmVwb3J0X3llYXIsIGVudGl0eV90eXBlX2Rlc2MsY29udHJpYnV0b3JfcHJlZml4LCBjb250cmlidXRvcl9uYW1lLCBjb250cmlidXRvcl9maXJzdF9uYW1lLCBjb250cmlidXRvcl9sYXN0X25hbWUsIGNvbnRyaWJ1dG9yX21pZGRsZV9uYW1lLCBjb250cmlidXRvcl9zdHJlZXRfMSxjb250cmlidXRvcl9jaXR5LCBjb250cmlidXRvcl9zdGF0ZSwgY29udHJpYnV0b3JfemlwLGNvbnRyaWJ1dG9yX2VtcGxveWVyLCBjb250cmlidXRvcl9vY2N1cGF0aW9uLCBjb250cmlidXRpb25fcmVjZWlwdF9kYXRlLCBjb250cmlidXRpb25fcmVjZWlwdF9hbW91bnQsIGNvbnRyaWJ1dG9yX2FnZ3JlZ2F0ZV95dGQsbWVtb190ZXh0LHBkZl91cmwsIGNhbmRpZGF0ZV9pZCwgY2FuZGlkYXRlX2VsZWN0aW9uX3llYXIpCmBgYAoKUTE6IERvIG1vcmUgTWFyeWxhbmRlcnMgZG9uYXRlIHRvIGluLXN0YXRlIG9yIG91dC1vZi1zdGF0ZSBjYW5kaWRhdGVzPyAKCmBgYHtyfQpmaW5hbF9kYXRhX3N0YXRlcyA8LSBmaW5hbF9kYXRhIHw+CiAgbXV0YXRlKHN0YXRlID0gc3Vic3RyKGNhbmRpZGF0ZV9pZCwgMywgNCkpCmBgYAoKYGBge3J9CnN0YXRlX2NvbnRyaWJ1dGlvbnMgPC0gZmluYWxfZGF0YV9zdGF0ZXMgfD4KICBncm91cF9ieShzdGF0ZSkgfD4KICBzdW1tYXJpc2UoCiAgICBjb250cmlidXRpb25fY291bnQgPSBuKCksICAgICAgICAgICAgICAgIAogICAgdG90YWxfY29udHJpYnV0aW9uID0gc3VtKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCwgbmEucm0gPSBUUlVFKSAgCiAgKQpgYGAKCmBgYHtyfQptYXJ5bGFuZF9jb250cmliIDwtIHN0YXRlX2NvbnRyaWJ1dGlvbnMgfD4KICBmaWx0ZXIoc3RhdGUgPT0gIk1EIikgfD4KICBzdW1tYXJpc2UodG90YWxfbWFyeWxhbmRfY29udHJpYiA9IHN1bSh0b3RhbF9jb250cmlidXRpb24sIG5hLnJtID0gVFJVRSkpCgoKb3RoZXJfc3RhdGVzX2NvbnRyaWIgPC0gc3RhdGVfY29udHJpYnV0aW9ucyB8PgogIGZpbHRlcihzdGF0ZSAhPSAiTUQiKSB8PgogIHN1bW1hcmlzZSh0b3RhbF9vdGhlcl9zdGF0ZXNfY29udHJpYiA9IHN1bSh0b3RhbF9jb250cmlidXRpb24sIG5hLnJtID0gVFJVRSkpCgoKY29tcGFyaXNvbiA8LSBkYXRhLmZyYW1lKAogIHN0YXRlID0gYygiTWFyeWxhbmQiLCAiT3RoZXIgU3RhdGVzIiksCiAgdG90YWxfY29udHJpYnV0aW9uID0gYyhtYXJ5bGFuZF9jb250cmliJHRvdGFsX21hcnlsYW5kX2NvbnRyaWIsIG90aGVyX3N0YXRlc19jb250cmliJHRvdGFsX290aGVyX3N0YXRlc19jb250cmliKQopCmBgYAoKCkE6IE1vbnRhbmEgd2FzIHN1cnByaXNpbmdseSB0aGUgc3RhdGUgd2l0aCB0aGUgbW9zdCBjb250cmlidXRpb25zIC0tLSBlZGdpbmcgTWFyeWxhbmQgd2l0aCAyMDIgbW9yZSBjb250cmlidXRpb25zIE1hcnlsYW5kLiBNYXJ5bGFuZCByZWNlaXZlZCB0aGUgaGlnaGVzdCB0b3RhbCBzdW0gaG93ZXZlciwgd2l0aCAkNSw1MTYsNTYyLjI0LiBUaGF0IHdhcyAkNCwwNzQsMjI2LjA3IG1vcmUgdGhhbiB0aGUgbmV4dCBoaWdoZXN0IHN0YXRlLCB3aGljaCB3YXMgTW9udGFuYS4gVGhlIG90aGVyIHN0YXRlcyBjb21iaW5lZCByZWNpZXZlZCAkNywzNTgsOTcwLCBhIGxpdHRsZSBsZXNzIHRoYW4gdHdvIG1pbGxpb24gbW9yZSB0aGFuIGp1c3QgdGhlIHN0YXRlIG9mIE1hcnlsYW5kLiAKCgpRMjogV2hpY2ggb3V0LW9mLXN0YXRlIGNhbmRpZGF0ZXMgcmVjZWl2ZWQgdGhlIG1vc3QgZG9uYXRpb25zIGFuZCB0aGUgZ3JlYXRlc3QgYW1vdW50IG9mIG1vbmV5IGluIGRvbmF0aW9ucz8gCgpgYGB7cn0KZmluYWxfZGF0YV9ub19tZCA8LSBmaW5hbF9kYXRhX3N0YXRlcyB8PgogIGZpbHRlcihzdGF0ZSAhPSAiTUQiKQpgYGAKCmBgYHtyfQpjb250cmlidXRpb25zX3N1bW1hcnkgPC0gZmluYWxfZGF0YV9ub19tZCB8PgogIGdyb3VwX2J5KGNvbW1pdHRlZV9uYW1lKSB8PgogIHN1bW1hcmlzZSgKICAgIG51bV9jb250cmlidXRpb25zID0gbigpLCAKICAgIHRvdGFsX2NvbnRyaWJ1dGlvbl9zdW0gPSBzdW0oY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50LCBuYS5ybSA9IFRSVUUpIAogICkgfD4KICBhcnJhbmdlKGNvbW1pdHRlZV9uYW1lKQpgYGAKCkEyOiBKb24gVGVzdGVyLCBTaGVycm9kIEJyb3duIGFuZCBSdWJlbiBHYWxsZWdvIHdlcmUgdGhlIHRvcCB0aHJlZSBpbiB0aGF0IG9yZGVyIGZvciBib3RoIGNvbnRyaWJ1dGlvbnMgcmVjaWV2ZWQgYW5kIHRoZSBzdW0gb2YgY29udHJpYnV0aW9ucy4gVGhlIHNpbWlsYXJpdHkgYmV0d2VlbiB0aGUgdGhyZWUgb2YgdGhlbSBpcyB0aGF0IHRoZXkgd2VyZSBhbGwgRGVtb2NyYXRzIHJ1bm5pbmcgaW4gdGlnaHRseSBjb250ZXN0ZWQgcmFjZXMuIEJyb3duIHdhcyB0aGUgb25seSB0byBsb3NlIGhpcyByYWNlLiBKb24gVGVzdGVyIGFsc28gY2xlYXJseSByZWNpZXZlZCBtb3JlIHRoYW4gdGhlIG90aGVyIHR3byAtLS0gd2hpY2ggZXhwbGFpbnMgd2h5IE1vbnRhbmEgcmVjZWl2ZWQgc28gbWFueSBtb3JlIG91dC1vZi1zdGF0ZSBjb250cmlidXRpb25zIHRoYW4gb3RoZXIgc3RhdGVzLiBNb250YW5hbnMgZm9yIFRlc3RlciByZWNlaXZlZCAzLDY3OSBtb3JlIGNvbnRyaWJ1dGlvbnMgYW5kICQyMzgsMDE3Ljk2IG1vcmUgaW4gdG90YWwgY29udHJpYnV0aW9ucyBjb21wYXJlZCB0byBGcmllbmRzIG9mIFNoZXJyb2QgQnJvd24uCgpRMzogV2hhdCBhcmUgdGhlIGRlbW9ncmFwaGljcyBvZiBwZW9wbGUgd2hvIGRvbmF0ZSB0byBNYXJ5bGFuZCByYWNlcyBvbmx5PyBUbyBvdXQtb2Ytc3RhdGUgcmFjZXMgb25seT8KClN0ZXAgMTogZmluZCBwZW9wbGUgd2hvIGRvbmF0ZSB0byBPTkxZIE1hcnlsYW5kIHJhY2VzLgpgYGB7cn0KCm1hcnlsYW5kX29ubHlfZG9ub3JzIDwtIGZpbmFsX2RhdGFfc3RhdGVzfD4KICBncm91cF9ieShjb250cmlidXRvcl9uYW1lKSB8PiAgICAgICAgICAgICAgICAKICBzdW1tYXJpemUob25seV9tZCA9IGFsbChzdGF0ZSA9PSAiTUQiKSkgfD4KICBmaWx0ZXIob25seV9tZCkgfD4gICAgICAgICAgICAgICAgICAgICAgICAgIAogIHNlbGVjdChjb250cmlidXRvcl9uYW1lKSAgICAgICAgICAgICAgICAgICAgCgpmdWxsX21hcnlsYW5kX29ubHlfZG9ub3JzIDwtIGZpbmFsX2RhdGFfc3RhdGVzIHw+CiAgIGZpbHRlcihjb250cmlidXRvcl9uYW1lICVpbiUgbWFyeWxhbmRfb25seV9kb25vcnMkY29udHJpYnV0b3JfbmFtZSkKCgp6aXBzX2Z1bGxfbWFyeWxhbmRfb25seV9kb25vcnMgPC0gZnVsbF9tYXJ5bGFuZF9vbmx5X2Rvbm9ycyB8PgogIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX25hbWUsIGNvbnRyaWJ1dG9yX3ppcCkgfD4KICBzdW1tYXJpemUoCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgICAgICAgICAgICAKICAgIHRvdGFsX2RvbmF0ZWQgPSBzdW0oY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50KSAKICApfD4KICBhcnJhbmdlKGRlc2MobnVtX2RvbmF0aW9ucykpICAKCm1kX3ppcF9zdW1tYXJ5IDwtIHppcHNfZnVsbF9tYXJ5bGFuZF9vbmx5X2Rvbm9ycyB8PgogIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX3ppcCkgfD4gICAgICAgICAgICAgIAogIHN1bW1hcml6ZSgKICAgIG51bV9kb25hdGlvbnMgPSBuKCksICAgICAgICAgICAgICAgICAgICAgIAogICAgdG90YWxfZG9uYXRlZCA9IHN1bSh0b3RhbF9kb25hdGVkKSAgICAgIAogICkgfD4KICBhcnJhbmdlKGRlc2MobnVtX2RvbmF0aW9ucykpIAoKYGBgCmBgYHtyfQphbGxfemN0YSA8LSBnZXRfYWNzKAogIGdlb2dyYXBoeSA9ICJ6Y3RhIiwKICB2YXJpYWJsZXMgPSBjKAogIkIwMTAwM18wMDEiLCAKICAgICAiQjAxMDAyXzAwMSIsICM9ICJtZWRpYW5fYWdlIiwKICJCMTkwMTNfMDAxIiwgIyA9ICJtZWRpYW5faW5jb21lIiwKICAiQjAyMDAxXzAwMiIsICMgPSAid2hpdGVfYWxvbmUiLAogICAgICJCMDIwMDFfMDAzIiwgIyA9ICJibGFja19hbG9uZSIsCiJCMDIwMDFfMDA0IiwgIyA9ICJuYXRpdmVfYW1lcmljYW4iLAogICAgIkIwMjAwMV8wMDUiLCAjPSAiYXNpYW5fYWxvbmUiLAogIkIwMjAwMV8wMDYiLCAjID0gImhhd2FpaWFuX3BhY2lmaWMiLAoiQjAyMDAxXzAwNyIsICAjID0gIm90aGVyX3JhY2UiLAogICAgIkIwMjAwMV8wMDgiLCAjID0gInR3b19vcl9tb3JlX3JhY2VzIgoiQjAzMDAyXzAxMkUiKSwKICAKICB5ZWFyID0gMjAyMiwKICBzdXJ2ZXkgPSAiYWNzNSIsCiAgb3V0cHV0ID0gIndpZGUiCikKCmFsbF96Y3RhIDwtIGFsbF96Y3RhICU+JQogIHJlbmFtZSgKICAgIHRvdGFsX3BvcHVsYXRpb24gPSBCMDEwMDNfMDAxRSwgICAgICAKICAgIG1lZGlhbl9hZ2UgPSBCMDEwMDJfMDAxRSwgICAgICAgICAgICAKICAgIG1lZGlhbl9pbmNvbWUgPSBCMTkwMTNfMDAxRSwgICAgICAgIAogICAgd2hpdGVfYWxvbmUgPSBCMDIwMDFfMDAyRSwgICAgICAgICAgCiAgICBibGFja19hbG9uZSA9IEIwMjAwMV8wMDNFLCAgICAgICAgIAogICAgbmF0aXZlX2FtZXJpY2FuID0gQjAyMDAxXzAwNEUsICAgICAgCiAgICBhc2lhbl9hbG9uZSA9IEIwMjAwMV8wMDVFLCAgICAgICAgICAKICAgIGhhd2FpaWFuX3BhY2lmaWMgPSBCMDIwMDFfMDA2RSwgICAgIAogICAgb3RoZXJfcmFjZSA9IEIwMjAwMV8wMDdFLCAgICAgICAgICAgCiAgICB0d29fb3JfbW9yZV9yYWNlcyA9IEIwMjAwMV8wMDhFLAogICAgaGlzcGFuaWNfb3JfbGF0aW5vID0gQjAzMDAyXzAxMkUKICApCgpgYGAKYGBge3J9Cgp6aXBzX2Z1bGxfbWFyeWxhbmRfb25seV9kb25vcnMgPC0gemlwc19mdWxsX21hcnlsYW5kX29ubHlfZG9ub3JzIHw+CiAgbXV0YXRlKAogICAgY29udHJpYnV0b3JfemlwID0gc3Vic3RyKGNvbnRyaWJ1dG9yX3ppcCwgMSwgNSksCiAgICBjb250cmlidXRvcl96aXAgPSBzcHJpbnRmKCIlMDVzIiwgY29udHJpYnV0b3JfemlwKQogICkKCnppcHNfZnVsbF9tYXJ5bGFuZF9vbmx5X2Rvbm9ycyA8LSB6aXBzX2Z1bGxfbWFyeWxhbmRfb25seV9kb25vcnMgfD4KICBtdXRhdGUoY29udHJpYnV0b3JfemlwID0gYXMuY2hhcmFjdGVyKGNvbnRyaWJ1dG9yX3ppcCkpCgptZXJnZWRfZGF0YV9tZCA8LSB6aXBzX2Z1bGxfbWFyeWxhbmRfb25seV9kb25vcnMgJT4lCiAgbGVmdF9qb2luKGFsbF96Y3RhLCBieSA9IGMoImNvbnRyaWJ1dG9yX3ppcCIgPSAiR0VPSUQiKSkKCnN1bW1hcml6ZWRfbWRfZG9ub3JfZGVtb3NfYnlfemlwIDwtIG1lcmdlZF9kYXRhX21kICU+JQogIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX3ppcCkgfD4KICBzdW1tYXJpemUoCiAgICB0b3RhbF9wb3B1bGF0aW9uID0gZmlyc3QodG90YWxfcG9wdWxhdGlvbiksICAKICAgIG1lZGlhbl9hZ2UgPSBmaXJzdChtZWRpYW5fYWdlKSwgICAgICAgICAgICAgCiAgICBtZWRpYW5faW5jb21lID0gZmlyc3QobWVkaWFuX2luY29tZSksICAgICAgIAogICAgd2hpdGVfYWxvbmUgPSBmaXJzdCh3aGl0ZV9hbG9uZSksICAgICAgICAgICAgCiAgICBibGFja19hbG9uZSA9IGZpcnN0KGJsYWNrX2Fsb25lKSwgICAgICAgICAgIAogICAgbmF0aXZlX2FtZXJpY2FuID0gZmlyc3QobmF0aXZlX2FtZXJpY2FuKSwgICAKICAgIGFzaWFuX2Fsb25lID0gZmlyc3QoYXNpYW5fYWxvbmUpLCAgICAgICAgICAgCiAgICBoYXdhaWlhbl9wYWNpZmljID0gZmlyc3QoaGF3YWlpYW5fcGFjaWZpYyksICAKICAgIG90aGVyX3JhY2UgPSBmaXJzdChvdGhlcl9yYWNlKSwgIAogICAgIGhpc3BhbmljX29yX2xhdGlubyA9IGZpcnN0KGhpc3BhbmljX29yX2xhdGlubyksCiAgICB0d29fb3JfbW9yZV9yYWNlcyA9IGZpcnN0KHR3b19vcl9tb3JlX3JhY2VzKSwKICAgIG51bV9kb25hdGlvbnMgPSBuKCksICAgICAgICAgICAgICAgICAgICAgIAogICAgdG90YWxfYW10X2RvbmF0ZWQgPSBzdW0odG90YWxfZG9uYXRlZCwgbmEucm0gPSBUUlVFKSAKICApIHw+IAogIGFycmFuZ2UoZGVzYyhudW1fZG9uYXRpb25zKSkgIHw+IAogIG11dGF0ZSgKICAgIHdoaXRlX2Fsb25lX3Blcl9jYXBpdGEgPSB3aGl0ZV9hbG9uZSAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBibGFja19hbG9uZV9wZXJfY2FwaXRhID0gYmxhY2tfYWxvbmUgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgbmF0aXZlX2FtZXJpY2FuX3Blcl9jYXBpdGEgPSBuYXRpdmVfYW1lcmljYW4gLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgYXNpYW5fYWxvbmVfcGVyX2NhcGl0YSA9IGFzaWFuX2Fsb25lIC8gdG90YWxfcG9wdWxhdGlvbiwKICAgIGhhd2FpaWFuX3BhY2lmaWNfcGVyX2NhcGl0YSA9IGhhd2FpaWFuX3BhY2lmaWMgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgb3RoZXJfcmFjZV9wZXJfY2FwaXRhID0gb3RoZXJfcmFjZSAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICAgaGlzcGFuaWNfb3JfbGF0aW5vX3Blcl9jYXBpdGEgPSBoaXNwYW5pY19vcl9sYXRpbm8gLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgdHdvX29yX21vcmVfcmFjZXNfcGVyX2NhcGl0YSA9IHR3b19vcl9tb3JlX3JhY2VzIC8gdG90YWxfcG9wdWxhdGlvbiwKICAgIG1lZGlhbl9pbmNvbWVfcGVyX2NhcGl0YSA9IG1lZGlhbl9pbmNvbWUgLyB0b3RhbF9wb3B1bGF0aW9uCiAgKSB8PgogICBtdXRhdGUoCiAgICB3aGl0ZV9hbG9uZV9wZXJjZW50ID0gd2hpdGVfYWxvbmVfcGVyX2NhcGl0YSAqIDEwMCwKICAgIGJsYWNrX2Fsb25lX3BlcmNlbnQgPSBibGFja19hbG9uZV9wZXJfY2FwaXRhICogMTAwLAogICAgbmF0aXZlX2FtZXJpY2FuX3BlcmNlbnQgPSBuYXRpdmVfYW1lcmljYW5fcGVyX2NhcGl0YSAqIDEwMCwKICAgIGFzaWFuX2Fsb25lX3BlcmNlbnQgPSBhc2lhbl9hbG9uZV9wZXJfY2FwaXRhICogMTAwLAogICAgaGF3YWlpYW5fcGFjaWZpY19wZXJjZW50ID0gaGF3YWlpYW5fcGFjaWZpY19wZXJfY2FwaXRhICogMTAwLAogICAgb3RoZXJfcmFjZV9wZXJjZW50ID0gb3RoZXJfcmFjZV9wZXJfY2FwaXRhICogMTAwLAogICAgaGlzcGFuaWNfb3JfbGF0aW5vX3BlcmNlbnQgPSBoaXNwYW5pY19vcl9sYXRpbm9fcGVyX2NhcGl0YSAqMTAwLAogICAgdHdvX29yX21vcmVfcmFjZXNfcGVyY2VudCA9IHR3b19vcl9tb3JlX3JhY2VzX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBtZWRpYW5faW5jb21lX3Blcl9jYXBpdGEgPSBtZWRpYW5faW5jb21lX3Blcl9jYXBpdGEgKiAxMDAKICApIHw+CiBtdXRhdGUoCiAgICBhbXRfZG9uYXRlZF9wZXJfcmVzaWRlbnQgPSB0b3RhbF9hbXRfZG9uYXRlZCAvIHRvdGFsX3BvcHVsYXRpb24KICApIHw+ICAgCiAgc2VsZWN0KHdoZXJlKH4gIWFsbChpcy5uYSguKSkpKQoKCmBgYApgYGB7cn0KCmNsZWFuZXJfbWRfZG9ub3JfZGVtb3MgPC0gc3VtbWFyaXplZF9tZF9kb25vcl9kZW1vc19ieV96aXAgfD4gCiAgICBzZWxlY3QoLW1hdGNoZXMoIl9wZXJfY2FwaXRhIiksIC0ibmF0aXZlX2FtZXJpY2FuIiwgLSJoYXdhaWlhbl9wYWNpZmljIiwgLSJvdGhlcl9yYWNlIiwgLSJ0d29fb3JfbW9yZV9yYWNlcyIsIC0id2hpdGVfYWxvbmUiLCAtImJsYWNrX2Fsb25lIiwgLSJhc2lhbl9hbG9uZSIpIAogCgoKYGBgCiNyZXBlYXQgZm9yIG91dCBvZiBzdGF0ZSBkb25vcnMgCgpgYGB7cn0Kb3V0X29mX3N0YXRlX2Rvbm9ycyA8LSBmaW5hbF9kYXRhX3N0YXRlcyB8PgogIGZpbHRlcihzdGF0ZSAhPSAiTUQiKQoKeG1hcnlsYW5kX2Rvbm9ycyA8LSBmaW5hbF9kYXRhX3N0YXRlcyB8PgogIGZpbHRlcihzdGF0ZSA9PSAiTUQiKQoKb3V0X29mX3N0YXRlX29ubHlfZG9ub3JzIDwtIG91dF9vZl9zdGF0ZV9kb25vcnMgfD4KICBmaWx0ZXIoIWNvbnRyaWJ1dG9yX25hbWUgJWluJSB4bWFyeWxhbmRfZG9ub3JzJGNvbnRyaWJ1dG9yX25hbWUpICB8Pgpncm91cF9ieShjb250cmlidXRvcl9uYW1lLCBjb250cmlidXRvcl96aXApIHw+CiAgc3VtbWFyaXplKAogICAgbnVtX2RvbmF0aW9ucyA9IG4oKSwgICAgICAgICAgICAKICAgIHRvdGFsX2RvbmF0ZWQgPSBzdW0oY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50KSAgCiAgKSB8PgogIGFycmFuZ2UoZGVzYyhudW1fZG9uYXRpb25zKSkgIAoKCm91dF9vZl9zdGF0ZV9vbmx5X2Rvbm9ycyA8LSBvdXRfb2Zfc3RhdGVfb25seV9kb25vcnMgfD4KICBtdXRhdGUoCiAgICBjb250cmlidXRvcl96aXAgPSBzdWJzdHIoY29udHJpYnV0b3JfemlwLCAxLCA1KSwKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IHNwcmludGYoIiUwNXMiLCBjb250cmlidXRvcl96aXApCiAgKQoKCmBgYApgYGB7cn0KCm1lcmdlZF9kYXRhX29vcyA8LSBvdXRfb2Zfc3RhdGVfb25seV9kb25vcnN8PgogIGxlZnRfam9pbihhbGxfemN0YSwgYnkgPSBjKCJjb250cmlidXRvcl96aXAiID0gIkdFT0lEIikpCgpjbGVhbmVyX29vc19kb25vcl9kZW1vcyA8LSBtZXJnZWRfZGF0YV9vb3MgIHw+CiAgIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX3ppcCkgfD4KICBzdW1tYXJpemUoCiAgICB0b3RhbF9wb3B1bGF0aW9uID0gZmlyc3QodG90YWxfcG9wdWxhdGlvbiksIAogICAgbWVkaWFuX2FnZSA9IGZpcnN0KG1lZGlhbl9hZ2UpLCAgICAgICAgICAgICAgCiAgICBtZWRpYW5faW5jb21lID0gZmlyc3QobWVkaWFuX2luY29tZSksICAgICAgICAKICAgIHdoaXRlX2Fsb25lID0gZmlyc3Qod2hpdGVfYWxvbmUpLCAgICAgICAgIAogICAgYmxhY2tfYWxvbmUgPSBmaXJzdChibGFja19hbG9uZSksICAgICAgICAgICAgCiAgICBuYXRpdmVfYW1lcmljYW4gPSBmaXJzdChuYXRpdmVfYW1lcmljYW4pLCAgIAogICAgYXNpYW5fYWxvbmUgPSBmaXJzdChhc2lhbl9hbG9uZSksICAgICAgICAgICAKICAgIGhhd2FpaWFuX3BhY2lmaWMgPSBmaXJzdChoYXdhaWlhbl9wYWNpZmljKSwKICAgIG90aGVyX3JhY2UgPSBmaXJzdChvdGhlcl9yYWNlKSwgICAgIAogICAgaGlzcGFuaWNfb3JfbGF0aW5vID0gZmlyc3QoaGlzcGFuaWNfb3JfbGF0aW5vKSwKICAgIHR3b19vcl9tb3JlX3JhY2VzID0gZmlyc3QodHdvX29yX21vcmVfcmFjZXMpLAogICAgbnVtX2RvbmF0aW9ucyA9IG4oKSwgICAgICAgICAgICAgICAgICAgICAgCiAgICB0b3RhbF9hbXRfZG9uYXRlZCA9IHN1bSh0b3RhbF9kb25hdGVkLCBuYS5ybSA9IFRSVUUpIAogICkgfD4gCiAgYXJyYW5nZShkZXNjKG51bV9kb25hdGlvbnMpKSAgfD4gCiAgbXV0YXRlKAogICAKICAgIHdoaXRlX2Fsb25lX3Blcl9jYXBpdGEgPSB3aGl0ZV9hbG9uZSAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBibGFja19hbG9uZV9wZXJfY2FwaXRhID0gYmxhY2tfYWxvbmUgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgbmF0aXZlX2FtZXJpY2FuX3Blcl9jYXBpdGEgPSBuYXRpdmVfYW1lcmljYW4gLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgYXNpYW5fYWxvbmVfcGVyX2NhcGl0YSA9IGFzaWFuX2Fsb25lIC8gdG90YWxfcG9wdWxhdGlvbiwKICAgIGhhd2FpaWFuX3BhY2lmaWNfcGVyX2NhcGl0YSA9IGhhd2FpaWFuX3BhY2lmaWMgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgb3RoZXJfcmFjZV9wZXJfY2FwaXRhID0gb3RoZXJfcmFjZSAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBoaXNwYW5pY19vcl9sYXRpbm9fcGVyX2NhcGl0YSA9IGhpc3BhbmljX29yX2xhdGlubyAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICB0d29fb3JfbW9yZV9yYWNlc19wZXJfY2FwaXRhID0gdHdvX29yX21vcmVfcmFjZXMgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgbWVkaWFuX2luY29tZV9wZXJfY2FwaXRhID0gbWVkaWFuX2luY29tZSAvIHRvdGFsX3BvcHVsYXRpb24KICApIHw+CiAgIG11dGF0ZSgKICAKICAgIHdoaXRlX2Fsb25lX3BlcmNlbnQgPSB3aGl0ZV9hbG9uZV9wZXJfY2FwaXRhICogMTAwLAogICAgYmxhY2tfYWxvbmVfcGVyY2VudCA9IGJsYWNrX2Fsb25lX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBuYXRpdmVfYW1lcmljYW5fcGVyY2VudCA9IG5hdGl2ZV9hbWVyaWNhbl9wZXJfY2FwaXRhICogMTAwLAogICAgYXNpYW5fYWxvbmVfcGVyY2VudCA9IGFzaWFuX2Fsb25lX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBoYXdhaWlhbl9wYWNpZmljX3BlcmNlbnQgPSBoYXdhaWlhbl9wYWNpZmljX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBvdGhlcl9yYWNlX3BlcmNlbnQgPSBvdGhlcl9yYWNlX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBoaXNwYW5pY19vcl9sYXRpbm9fcGVyY2VudCA9IGhpc3BhbmljX29yX2xhdGlub19wZXJfY2FwaXRhICoxMDAsCiAgICB0d29fb3JfbW9yZV9yYWNlc19wZXJjZW50ID0gdHdvX29yX21vcmVfcmFjZXNfcGVyX2NhcGl0YSAqIDEwMCwKICAgIG1lZGlhbl9pbmNvbWVfcGVyX2NhcGl0YSA9IG1lZGlhbl9pbmNvbWVfcGVyX2NhcGl0YSAqIDEwMCAgCiAgKSAKCmNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zIDwtIGNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zIHw+IHNlbGVjdCgtbWF0Y2hlcygiX3Blcl9jYXBpdGEiKSwgLSJuYXRpdmVfYW1lcmljYW4iLCAtImhhd2FpaWFuX3BhY2lmaWMiLCAtIm90aGVyX3JhY2UiLCAtInR3b19vcl9tb3JlX3JhY2VzIiwgLSJ3aGl0ZV9hbG9uZSIsIC0iYmxhY2tfYWxvbmUiLCAtImFzaWFuX2Fsb25lIikgfD4gCiAgCiAgbXV0YXRlKAogICAgYW10X2RvbmF0ZWRfcGVyX3Jlc2lkZW50ID0gdG90YWxfYW10X2RvbmF0ZWQgLyB0b3RhbF9wb3B1bGF0aW9uCiAgKSB8PgogIHNlbGVjdCh3aGVyZSh+ICFhbGwoaXMubmEoLikpKSkKCgpgYGAKYGBge3J9CmhlYWQobWVyZ2VkX2RhdGFfb29zKQpgYGAKCgpgYGB7cn0KY2xlYW5lcl9vb3NfZG9ub3JfZGVtb3MgfD4gICAKICBtdXRhdGUoCiAgICBjb250cmlidXRvcl96aXAgPSBhcy5jaGFyYWN0ZXIoY29udHJpYnV0b3JfemlwKSwgICAgICAgICAjIEVuc3VyZSBaSVAgY29kZXMgYXJlIHN0cmluZ3MKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IHN0cl9wYWQoY29udHJpYnV0b3JfemlwLCB3aWR0aCA9IDUsICAgICMgUGFkIHdpdGggbGVhZGluZyB6ZXJvcyB0byBlbnN1cmUgNSBkaWdpdHMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2lkZSA9ICJsZWZ0IiwgcGFkID0gIjAiKSwKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IGlmZWxzZShzdHJfZGV0ZWN0KGNvbnRyaWJ1dG9yX3ppcCwgIl5cXGR7NX0kIiksICAjIEtlZXAgb25seSB2YWxpZCA1LWRpZ2l0IFpJUCBjb2RlcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyaWJ1dG9yX3ppcCwgTkEpKQoKCmNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zIHw+IGFycmFuZ2UoZGVzYyhhbXRfZG9uYXRlZF9wZXJfcmVzaWRlbnQpKSB8PiB3cml0ZV9jc3YoImNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zLmNzdiIpCgpgYGAKCmBgYHtyfQpjbGVhbmVyX21kX2Rvbm9yX2RlbW9zIHw+IAogIG11dGF0ZSgKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IGFzLmNoYXJhY3Rlcihjb250cmlidXRvcl96aXApLCAgICAgICAgICMgRW5zdXJlIFpJUCBjb2RlcyBhcmUgc3RyaW5ncwogICAgY29udHJpYnV0b3JfemlwID0gc3RyX3BhZChjb250cmlidXRvcl96aXAsIHdpZHRoID0gNSwgICAgIyBQYWQgd2l0aCBsZWFkaW5nIHplcm9zIHRvIGVuc3VyZSA1IGRpZ2l0cwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWRlID0gImxlZnQiLCBwYWQgPSAiMCIpLAogICAgY29udHJpYnV0b3JfemlwID0gaWZlbHNlKHN0cl9kZXRlY3QoY29udHJpYnV0b3JfemlwLCAiXlxcZHs1fSQiKSwgICMgS2VlcCBvbmx5IHZhbGlkIDUtZGlnaXQgWklQIGNvZGVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJpYnV0b3JfemlwLCBOQSkpIHw+IAogIGFycmFuZ2UoZGVzYyhhbXRfZG9uYXRlZF9wZXJfcmVzaWRlbnQpKSB8PiB3cml0ZV9jc3YoImNsZWFuZXJfbWRfZG9ub3JfZGVtb3MuY3N2IikKYGBgCgoKY2xlYW5lcl9vb3NfZG9ub3JfZGVtb3MgfD4gd3JpdGVfY3N2KCJjbGVhbmVyX29vc19kb25vcl9kZW1vcy5jc3YiKQoKCgpJdCBsb29rcyBsaWtlIGluIHRoaXMgZGF0YSwgdGhlIHRvcCBjb250cmlidXRpbmcgemlwIGNvZGVzIGFyZSB0aGUgc2FtZSBmb3Igb3V0LW9mLXN0YXRlIGFuZCBpbi1zdGF0ZSBkb25hdGlvbnMuIFRoZSB0b3Agb3V0LW9mLXN0YXRlIGRvbm9ycyBkb25hdGVkIG11Y2ggbW9yZSB0aGFuIHRoZSBpbi1zdGF0ZSBkb25vcnMsIGFuZCB0aGVyZSB3ZXJlIG1vcmUgb2YgdGhlbSBpbiB0aGUgdG9wIHppcCBjb2Rlcy4gQSB0b3AgaW4tc3RhdGUgZG9ub3IgemlwIGNvZGUgaXMgQW5hcG9saXMsIGFuZCBkb2Vzbid0IGFwcGVhciBpbiB0aGUgdG9wIHRlbiB6aXAgY29kZXMgZm9yIG91dC1vZi1zdGF0ZS4KCkFzIHdlIGtlZXAgZ29pbmcgdG8gYW5zd2VyIHRoaXMgcXVlc3Rpb24sIHdlIHNob3VsZCBjYWxjdWxhdGUgdGhlIGFtb3VudCBkb25hdGVkIHBlciBwZXJzb24uIFdlIHNob3VsZCBjb25zaWRlciBwcmVzZW50aW5nIHRoaXMgZGF0YSB3aXRoIHR3byBtYXBzIHNpZGUtYnktc2lkZS4gCgoKIyBRdWVzdGlvbiA0OiBBbW9uZyB0b3AgTWFyeWxhbmQgZG9ub3JzLCB3aGF0IHByb2Zlc3Npb25zIGRvbmF0ZSB0aGUgbW9zdCBtb25leSB0byBzZW5hdGUgY2FtcGFpZ25zPyAKCmBgYHtyfQppbmRpdmlkdWFsX2Rvbm9ycyAgPC0gZmluYWxfZGF0YV9zdGF0ZXN8Pgpncm91cF9ieShjb250cmlidXRvcl9uYW1lLCBjb250cmlidXRvcl96aXAsIGNvbnRyaWJ1dG9yX29jY3VwYXRpb24sIGNvbnRyaWJ1dG9yX2VtcGxveWVyKSB8PiAKICBzdW1tYXJpemUoCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgICAgICAgICAgICAgIAogICAgdG90YWxfZG9uYXRlZCA9IHN1bShjb250cmlidXRpb25fcmVjZWlwdF9hbW91bnQpIAogICkgfD4KICBhcnJhbmdlKGRlc2MobnVtX2RvbmF0aW9ucykpICAKCmpvYnNfdG9fY2xlYW4gPC0gaW5kaXZpZHVhbF9kb25vcnMgfD4gCiAgZ3JvdXBfYnkoY29udHJpYnV0b3Jfb2NjdXBhdGlvbikgfD4KICBzdW1tYXJpemUoCiAgICBudW1iZXJfam9icyA9IG4oKSwKICAgIG51bV9kb25hdGlvbnMgPSBuKCksICAKICAgICB0b3RhbF9kb25hdGlvbnMgPSBzdW0odG90YWxfZG9uYXRlZCkKICApIHw+IGFycmFuZ2UoZGVzYyhudW1iZXJfam9icykpIHw+CndyaXRlX2Nzdigiam9ic190b19jbGVhbi5jc3YiKQoKYGBgCgpgYGB7cn0KYm9zc190b19jbGVhbiAgPC0gaW5kaXZpZHVhbF9kb25vcnMgfD4gCiAgZ3JvdXBfYnkoY29udHJpYnV0b3JfZW1wbG95ZXIpIHw+CiAgc3VtbWFyaXplKAogICAgbnVtYmVyX2pvYnMgPSBuKCksCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgCiAgICAgdG90YWxfZG9uYXRpb25zID0gc3VtKHRvdGFsX2RvbmF0ZWQpCiAgKSB8PiBhcnJhbmdlKGRlc2MobnVtYmVyX2pvYnMpKSB8Pgp3cml0ZV9jc3YoImJvc3NfdG9fY2xlYW4uY3N2IikKYGBgCgoKYGBge3J9CmNsZWFuX2VtcGxveWVyIDwtIHJlYWRfY3N2KCJjbGVhbmVkX2Jvc3MuY3N2IikKY2xlYW5fb2NjdXBhdGlvbiA8LSByZWFkX2NzdigiY2xlYW5fam9icy5jc3YiKQoKY2xlYW5fb2NjdXBhdGlvbiB8PiAKICBncm91cF9ieShjbGVhbmVkX2pqb2JzKSAgfD4gCiAgc3VtbWFyaXplKAogICAgbnVtYmVyX2pvYnMgPSBuKCksCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgCiAgICAgdG90YWxfZG9uYXRlZCA9IHN1bSh0b3RhbF9kb25hdGlvbnMpKSB8PiAKICBhcnJhbmdlKGRlc2MobnVtYmVyX2pvYnMpKQoKYGBgCmBgYHtyfQpjbGVhbl9vY2N1cGF0aW9uIHw+IAogIGdyb3VwX2J5KGNsZWFuZWRfampvYnMpICB8PiAKICBzdW1tYXJpemUoCiAgICBudW1iZXJfam9icyA9IG4oKSwKICAgIG51bV9kb25hdGlvbnMgPSBuKCksICAKICAgICB0b3RhbF9kb25hdGVkID0gc3VtKHRvdGFsX2RvbmF0aW9ucykpIHw+IAogIGFycmFuZ2UoZGVzYyh0b3RhbF9kb25hdGVkKSkKCmBgYAoKCmBgYHtyfQpjbGVhbl9lbXBsb3llciB8PiAKICBncm91cF9ieShjbGVhbmVkX2Jvc3MpIHw+CiAgc3VtbWFyaXplKAogICAgbnVtYmVyX2pvYnMgPSBuKCksCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgCiAgICAgdG90YWxfZG9uYXRlZCA9IHN1bSh0b3RhbF9kb25hdGlvbnMpCiAgKSB8PgogIGFycmFuZ2UoZGVzYyhudW1iZXJfam9icykpCmBgYAoKClRvIGFuc3dlciB0aGlzIHF1ZXN0aW9uLCBJIHB1dCBhIGNzdiBvZiBvY2N1cGF0aW9ucyBpbnRvIE9wZW5SZWZpbmUuIFdlIG9yaWdpbmFsbHkgcGxhbm5lZCB0byBsaW1pdCB0aGUgZGF0YSBzZXQsIGJ1dCBJIGZvdW5kIHRoYXQgdGhlcmUgd2VyZSBvbmx5IDEsOTYzIGpvYiB0aXRsZXMgaW4gdGhlIGRhdGEgc2V0LCB3aGljaCBzZWVtZWQgbGlrZSBhIHJlYXNvbmFibGUgbnVtYmVyIHRvIHJlZmluZSBkb3duIGludG8gYSBzbWFsbGVyIGxpc3Qgb2Ygam9icy4gCgpUbyBkbyB0aGlzLCBJIGdyb3VwZWQgY2VydGFpbiBqb2JzIGludG8gY2F0ZWdvcmllcyBsaWtlICJkaXJlY3RvciIgYW5kICJleGVjdXRpdmUiIC0tIHNvIGpvYiB0aXRsZXMgbGlrZSAic2FsZXMgZGlyZWN0b3IiIHdlbnQgaW50byB0aGUgImRpcmVjdG9yIiBjYXRlZ29yeS4gCgpJIHRoaW5rIHRoZSBPcGVuUmVmaW5lIG1ldGhvZCBtYXkgYmUgZmxhd2VkL25vdCB0ZWxsIHVzIHZlcnkgbXVjaCBiZWNhdXNlIEkgd2FzIG9ubHkgYWJsZSB0byBnZXQgdGhlIGxpc3QgZG93biB0byAxLDQ2NCBqb2JzIGFmdGVyIGFib3V0IDEgaG91ciBvZiByZWZpbmluZy4gSSBhbHNvIHdvcnJ5IHRoYXQgdGhlIGNhdGVnb3JpemluZyBtZXRob2QgSSB1c2VkIG9ic3VyZXMgaW5mb3JtYXRpb24gdGhhdCBtaWdodCBiZSBpbXBvcnRhbnQgLS0gRGlyZWN0b3Igb2YgU2FsZXMgaXMgZGlmZmVyZW50IGZyb20gRGlyZWN0b3Igb2YgRWR1Y2F0aW9uLCBmb3IgZXhhbXBsZSwgYW5kIHRoZXNlIGpvYnMgd2VyZSBncm91cGVkIGludG8gdGhlIHNhbWUgcG9zaXRpb24uIEFuZCB0aGVyZSBhcmUgc3VjaCB2YXJpYXRpb25zIGluIGpvYiB0aXRsZSB0aGF0IEkgd2FzIG5vdCBhYmxlIHRvIGNhdGVnb3JpemUgYWxsIGpvYiB0aXRsZXMgd2VsbC4gCgpXaGF0IHdlIGNhbiB0ZWxsIGZyb20gdGhpcyBkYXRhIGlzIHRoYXQgdGhlIG1vc3QgZnJlcXVlbnRseS1oZWxkIGpvYnMgYW1vbmcgTWFyeWxhbmQgZG9ub3JzIGFyZSBsZWFkZXJzaGlwL21hbmFnZW1lbnQgcG9zaXRpb25zLCBzbyBsaWtlbHkgd2VsbC1wYWlkLiBUaGUgbW9zdCBtb25leSB3YXMgZG9uYXRlZCBieSBwZW9wbGUgd2hvIGFyZSBub3QgZW1wbG95ZWQgb3IgcmV0aXJlZC4gCgpXZSBzaG91bGQgY29uc2lkZXIgcmVwZWF0aW5nIHRoaXMgcXVlc3Rpb24gd2l0aCBpbmZvcm1hdGlvbiBhYm91dCBlbXBsb3llcnMuIEkndmUgc3RhcnRlZCB0byBkbyB0aGlzIGluIE9wZW5SZWZpbmUsIGJ1dCB0aGlzIHdpbGwgdGFrZSBsb25nZXIsIGJlY2F1c2UgdGhlcmUgYXJlIG1vcmUgdGhhbiA3LDAwMCBkaWZmZXJlbnQgZW1wbG95ZXJzLiBIb3dldmVyLCBtYW55IG9mIHRoZXNlIHNlZW0gdG8gYmUgYWJsZSB0byBiZSByZWNvbmNpbGVkIGluIE9wZW5SZWZpbmUuIEFuZCBJJ20gaW50ZXJlc3RlZCB0byBzZWUgaG93IG1hbnkgZG9uYXRpb25zL2hvdyBtdWNoIG1vbmV5IHdhcyBkb25hdGVkIGJ5IHBlb3BsZSB3aG8gd29yayBmb3IgdG9wIGVtcGxveWVycyBpbiBNYXJ5bGFuZCwgbGlrZSBKb2hucyBIb3BraW5zLiAKCgojUXVlc3Rpb24gNTogV2hhdOKAmXMgdGhlIG1ha2V1cCBvZiBkb25hdGlvbnMgcmVjZWl2ZWQgYnkgSG9nYW4gYW5kIEFsc29icm9va3M/IFdoYXQgcGVyY2VudGFnZSBvZiB0aGVpciBvdmVyYWxsIGRvbmF0aW9ucyB3ZXJlIGxhcmdlIGFtb3VudHMgb2YgbW9uZXkgKHRvIGJlIGRlZmluZWQsIGJ1dCA+ICQxMDAwLCBmb3IgZXhhbXBsZSkgdnMgc21hbGwgYW1vdW50cz8KCmBgYHtyfQpob2dhbl9maWx0ZXJlZF9kYXRhIDwtIGZpbmFsX2RhdGEgfD4KICBmaWx0ZXIoY29tbWl0dGVlX25hbWUgJWluJSBjKCJIT0dBTiBGT1IgTUFSWUxBTkQgSU5DLiIpKQpsYXJnZV9kb25hdGlvbl90aHJlc2hvbGQgPC0gMTAwMAoKaG9nYW5fZmlsdGVyZWRfZGF0YSB8PiBtdXRhdGUoIGRvbmF0aW9uX2NhdGVnb3J5ID0gaWZlbHNlKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCA+IGxhcmdlX2RvbmF0aW9uX3RocmVzaG9sZCwgIkxhcmdlIiwgIlNtYWxsIikgKQoKaG9nYW5fY2F0ZWdvcnlfdG90YWxzIDwtIGhvZ2FuX2ZpbHRlcmVkX2RhdGEgfD4KICBtdXRhdGUoZG9uYXRpb25fY2F0ZWdvcnkgPSBpZmVsc2UoY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50ID4gbGFyZ2VfZG9uYXRpb25fdGhyZXNob2xkLCAiTGFyZ2UiLCAiU21hbGwiKSkgfD4KICBncm91cF9ieShkb25hdGlvbl9jYXRlZ29yeSkgfD4KICBzdW1tYXJpc2UodG90YWxfYW1vdW50ID0gc3VtKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICJkcm9wIikKCmhvZ2FuX2NhdGVnb3J5X3RvdGFscyAlPiUgbXV0YXRlKCBwZXJjZW50YWdlID0gdG90YWxfYW1vdW50IC8gc3VtKHRvdGFsX2Ftb3VudCkgKiAxMDAgKQoKaG9nYW5fY2F0ZWdvcnlfdG90YWxzCmBgYAoKYGBge3J9CmFsc29icm9va3NfZmlsdGVyZWRfZGF0YSA8LSBmaW5hbF9kYXRhIHw+CiAgZmlsdGVyKGNvbW1pdHRlZV9uYW1lICVpbiUgYygiQUxTT0JST09LUyBGT1IgU0VOQVRFIikpCgpsYXJnZV9kb25hdGlvbl90aHJlc2hvbGQgPC0gMTAwMAoKYWxzb2Jyb29rc19jYXRlZ29yeV90b3RhbHMgPC0gYWxzb2Jyb29rc19maWx0ZXJlZF9kYXRhIHw+CiAgbXV0YXRlKGRvbmF0aW9uX2NhdGVnb3J5ID0gaWZlbHNlKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCA+IGxhcmdlX2RvbmF0aW9uX3RocmVzaG9sZCwgIkxhcmdlIiwgIlNtYWxsIikpIHw+CiAgZ3JvdXBfYnkoZG9uYXRpb25fY2F0ZWdvcnkpIHw+CiAgc3VtbWFyaXNlKHRvdGFsX2Ftb3VudCA9IHN1bShjb250cmlidXRpb25fcmVjZWlwdF9hbW91bnQsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpCgphbHNvYnJvb2tzX2NhdGVnb3J5X3RvdGFscyAgJT4lIG11dGF0ZSggcGVyY2VudGFnZSA9IHRvdGFsX2Ftb3VudCAvIHN1bSh0b3RhbF9hbW91bnQpICogMTAwICkKCmFsc29icm9va3NfY2F0ZWdvcnlfdG90YWxzCmBgYApBNTogSGVyZSB3ZSBzZWUgdGhhdCBIb2dhbiByZWNlaXZlcyBzaWduZmljYW50bHkgbW9yZSBtb25leSBpbiBnZW5lcmFsIGluIGNvbXBhcmlzb24gdG8gQWxzb2Jyb29rcy4gQWRkaXRpb25hbGx5LCBIb2dhbiByZWNlaXZlcyBtYW55IG1vcmUgbGFyZ2UgZG9uYXRpb25zIChpbiBleGNlc3Mgb2YgbWlsbGlvbnMpIGluIGNvbXBhcmlzb24gdG8gQWxzb2Jyb29rcy4gV2hlcmVhcywgdGhlIHNtYWxsIGRvbmF0aW9ucyBhcmUgYXJvdW5kIDYwMCwwMDAgbW9yZS4gVGhpcyBzaG93cyB0aGF0IGVpdGhlIEhvZ2FuIGhhcyBhIGxhcmdlciAiZmFuIGJhc2UiIG9mIHBlb3BsZSB3aG8gZG9uYXRlIHRvIGhpbSBvciBwZXJoYXBzIGhpcyBlbGVjdG9yYXRlIGlzIGp1c3Qgd2VhbHRoaWVyLiBBZGRpdGlvbmFsbHksaXQgd291bGQgYmUgaW50ZXJlc3RpbmcgdG8gbm90ZSB3aGV0aGVyIEhvZ2FuIGhhcyBhIGhpZ2hlciBhbW91bnQgb2YgZG9uYXRpb25zIGJlY2F1c2UgaGUgd2FzIGtub3duIGJlZm9yZS4gCg==